<?php
/**
 * 备份myqsl数据库，主要功能为自动获取sql，发送邮箱
 * 此类依赖于
 * 邮箱发送类    class.phpmailer
 * 压缩zip类     PHPZip
 */
class Backup{
    /* 邮箱实例 */
    private $mail;
    /* zip实例 */
    private $zip;

    private $dbConfig;

    private $mailConfig;

    private $sqlSavePath;

    private $zipSavePath;

    /* 初始化 */
    public function __construct(){
        static::register();
        BackupException::set();
        $this->mail = new PHPMailer;
        $this->zip = new PHPZip;

        $config = ($this->getConfig());
        $this->dbConfig = $config['db'];
        $this->mailConfig = $config['email'];
        $this->sqlSavePath = $config['sqlSavePath'];
        $this->zipSavePath = $config['zipSavePath'];
    }

    /* 开始备份 */
    public function start($address,$content){
        //生成sql文件
        $this->createSql($this->dbConfig,$this->sqlSavePath);

        $saveName = date('D-N').'.zip';
        $this->zip->Zip($this->sqlSavePath,$this->zipSavePath.$saveName);
        foreach($address as $email){
            $this->sendMail($email,$content,$this->zipSavePath.$saveName);
        }
    }

    /**
     * @param $config   数据库配置文件
     */
    private function createSql($config,$savePath){
        $host = $config['host'];
        $user = $config['username'];
        $password = $config['password'];

        //生成sql文件
        foreach($config['database'] as $db){
            Log::save("create database $db sql");
            $sqlPath = $savePath.$db.'.sql';
            //使用mysqldump生成sql,如果生成失败,使用PDO生成数据
            if(!$this->mysqldump($host,$user,$password,$db,$sqlPath)){
                Log::save('mysqldump::error');
                $dsn = "mysql:dbname=$db;host=$host";
                $this->backup($dsn,$user,$password);
            }
        }
    }

    /**
     * 通过mysqldump备份sql文件
     * @param $host
     * @param $user
     * @param $password
     * @param $db
     * @param $sqlPath
     * @return bool
     */
    private function mysqldump($host,$user,$password,$db,$sqlPath){
        $shell = "mysqldump -h $host -u $user -p$password $db > $sqlPath";
        exec($shell,$output,$returnVar);
        //检查系统返回状态码
        return ($returnVar === 0) ? true : false;
    }

    /**
     * 通过PDO生成sql文件
     * @param $dsn
     * @param $user
     * @param $password
     */
    private function backup($dsn,$user,$password){
        if(!extension_loaded('pdo') && !extension_loaded('pdo_mysql')){
            throw new BackupException('PDO扩展没有开启');
        }
        $pdo = new PDO($dsn,$user,$password);
//        try {
//            $insert = "INSERT INTO `$table` VALUES ( ";
//            $pdo->exec("set names 'utf8'");
//            $sql = "select * from $table";
//            $result = $pdo->query($sql);
//
//            for($i=0; $i<$result->columnCount(); $i++) {
//                $field[$result->getColumnMeta($i)['name']] = $result->getColumnMeta($i)['native_type'];
//            }
//
//            $data = $result->fetchAll(PDO::FETCH_ASSOC);
//            while(list($name,$info) = each($data)){
//                while(list($key,$value) = each($info)){
//                    //检查指针是否指向最后一位
//                    if(!current($info)){
//                        if(!current($data))
//                            $insert .= cheakType($key,$value,$field).')';
//                        else
//                            $insert .= cheakType($key,$value,$field).'),(';
//                        break;
//                    }
//                    $insert .= cheakType($key,$value,$field).',';
//                }
//            }
//        } catch (PDOException $e) {
//            die("Error!: " . $e->getMessage());
//        }
    }

    public function getConfig(){
        static $config;
        if(empty($config)){
            $config = include('config.php');
        }
        return $config;
    }

    /**
     * 自动加载
     * @param $classname
     */
    public static function Autoload($classname)
    {
        //Can't use __DIR__ as it's only in PHP 5.3+
        if($classname == 'PHPZip'){
            $filename = dirname(__FILE__).DIRECTORY_SEPARATOR.'PHPZip'.DIRECTORY_SEPARATOR.strtolower($classname).'.php';
        }else{
            $filename = dirname(__FILE__).DIRECTORY_SEPARATOR.'PHPMailer'.DIRECTORY_SEPARATOR.'class.'.strtolower($classname).'.php';
        }
        if (is_readable($filename)) {
            require $filename;
        }
    }

    /* 注册自动加载 */
    public static function register(){
        //SPL autoloading was introduced in PHP 5.1.2
        if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
            spl_autoload_register('Backup::Autoload', true, true);
        } else {
            spl_autoload_register('Backup::Autoload');
        }
    }

    /**
     * 发送邮件
     * @param $address
     * @param $content
     * @param $zip
     * @throws BackupException
     * @throws Exception
     * @throws phpmailerException
     */
    private function sendMail($address,$content,$zip){
        $stime = microtime(true);
        set_time_limit(0);
        $mail = $this->mail;
        $config = $this->mailConfig;
        //$mail->SMTPDebug = 3;                                 // Enable verbose debug output
        $mail->isSMTP();
        $mail->Host = $config['SMTPHost'];
        $mail->Port = $config['SMTPPort'];
        $mail->SMTPAuth = $config['SMTPAuth'];
        $mail->Username = $config['username'];
        $mail->Password = $config['password'];
        $mail->SMTPSecure = $config['SMTPSecure'];
        $mail->setFrom($config['username']);
        $mail->addAddress($address);               // Add a recipient
        $mail->addAttachment($zip);                   // Add attachments
        $mail->isHTML(true);                                    // Set email format to HTML
        $mail->Subject = 'Back up '.date('Y-m-d');
        $mail->Body    = $content;
        //$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';

        if(!$mail->send()) {
            throw new BackupException($mail->ErrorInfo);
        }
        $etime = microtime(true);
        $time = $etime-$stime;
        Log::save("Send e-mail to $address running time is $time seconds ");
    }
}
class BackupException extends Exception{
    public static function set(){
        set_exception_handler([__CLASS__,'getException']);
    }

    public static function getException($e){
        $content = $e->getMessage()."\r\n";
        $content .= 'in the '.$e->getFile().':'.$e->getLine();
        Log::save($content);
        print_r($e->getMessage());
    }
}

class Log{
    //写入日志
    public static function save($content){
        $savePath = dirname(__FILE__).DIRECTORY_SEPARATOR.'Log'.DIRECTORY_SEPARATOR;
        if (!file_exists($savePath))
            mkdir($savePath);

        $file = date("y-m-d").'.txt';
        $content = date('H:i:s:').$content."\r\n------------------------------------------------\r\n";
        file_put_contents($savePath.$file,$content,FILE_APPEND);
    }
}
$backup = new Backup();
$content = 'mysql database backup';
$backup->start(['13631246753@163.com','547740900@qq.com'],$content);
exit();